#ifndef __SPARC64_DEFNS_H__
#define __SPARC64_DEFNS_H__

#ifndef SPARC64
#define SPARC64
#endif

//////////////////////////////////////////////////////////////////////////
//include directives 
//////////////////////////////////////////////////////////////////////////
#include <thread.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/processor.h>
#include <sys/procset.h>
#include <pthread.h>
#include <sched.h>
#include <semaphore.h>
#include <alloca.h>
#include <strings.h>

//////////////////////////////////////////////////////////////////////////
//types 
//////////////////////////////////////////////////////////////////////////
typedef unsigned char      _u8;
typedef unsigned short     _u16;
typedef unsigned int       _u32;
typedef unsigned long long _u64;
typedef unsigned long long tick_t;
typedef _u64               ptr_t;

//////////////////////////////////////////////////////////////////////////
//constants
//////////////////////////////////////////////////////////////////////////
#define inline_ inline
#define CACHE_LINE_SIZE 64
#define PTHREAD_STACK_MIN ((size_t)_sysconf(_SC_THREAD_STACK_MIN))

#define get_marked_ref(_p)      ((void *)(((ptr_t)(_p)) | 1UL))
#define get_unmarked_ref(_p)    ((void *)(((ptr_t)(_p)) & ~1UL))
#define is_marked_ref(_p)       (((ptr_t)(_p)) & 1UL)

////////////////////////////////////////////////////////////////////////////////
//memory management
//------------------------------------------------------------------------------
//	WMB(): All preceding write operations must commit before any later writes.
//	RMB(): All preceding read operations must commit before any later reads.
//	MB():  All preceding memory accesses must commit before any later accesses.
////////////////////////////////////////////////////////////////////////////////
//#define ALIGNED_MALLOC(_s,_a)	memalign(_a, _s)
//#define ALIGNED_FREE(_p)		free(_p)
#define ALIGNED_MALLOC(_s,_a)	new unsigned char[_s]
#define ALIGNED_FREE(_p)		delete [] _p

extern "C" void MEMBAR_ALL(void);
extern "C" void MEMBAR_STORESTORE(void);
extern "C" void MEMBAR_LOADLOAD(void);

#define MB()  MEMBAR_ALL()
#define WMB() MEMBAR_STORESTORE()
#define RMB() MEMBAR_LOADLOAD()
#define VOLATILE /*volatile*/

//////////////////////////////////////////////////////////////////////////
//compare and set 
//////////////////////////////////////////////////////////////////////////
extern "C" int CASIO_internal(_u32 *, _u32, _u32);
extern "C" void * CASPO_internal(void *, void *, void *);
extern "C" _u64 CAS64O_internal(_u64 *, _u64, _u64);
#define CASIO(_a,_o,_n) (CASIO_internal((_u32*)(_a),(_u32)(_o),(_u32)(_n)))
#define CASPO(_a,_o,_n) (void*)(CAS64O_internal((_u64*)_a,(_u64)_o,(_u64)_n))
#define CAS32O(_a,_o,_n) (_u32)(CASIO_internal((_u32 *)_a,(_u32)_o,(_u32)_n))
#define CAS64(_a,_o,_n) (CAS64O_internal((_u64 *)_a,(_u64)_o,(_u64)_n))

static inline_ int FASIO(_u32 volatile * a, _u32 n) {
	_u32 no, o = *a;
	while ( (no = CASIO(a, o, n)) != o ) o = no;
	return o;
}

static inline_ void *FASPO(void* volatile * a, void *n) {
	void *no, *o = *(void **)a;
	while ( (no = CASPO(a, o, n)) != o ) o = no;
	return o;
}

//////////////////////////////////////////////////////////////////////////
//CPU counters
//////////////////////////////////////////////////////////////////////////
extern "C" tick_t RDTICK(void);

//////////////////////////////////////////////////////////////////////////
//bit operations
//////////////////////////////////////////////////////////////////////////

extern "C" _u32 POPC(_u32 x);

inline_ _u32 bit_count(const _u32 x) {
	return POPC(x);
}

inline_ _u32 bit_count64(const _u64 x) {
	return bit_count((_u32)x) + bit_count((_u32)(x>>32));
}

inline_ int fls(_u32 x) {
	x |= x >> 1;
	x |= x >> 2;
	x |= x >> 4;
	x |= x >> 8;
	x |= x >> 16;
	return POPC(x);
}

inline_ int first_lsb_bit_indx(_u32 x) {
	if(0==x) 
		return -1;
	return ffs(x)-1;
}

inline_ int first_msb_bit_indx(_u32 x) {
	if(0==x) 
		return -1;
	return fls(x)-1;
}

inline_ int first_lsb_bit_indx64(_u64 x) {
	if(0==x)
		return -1;
	else if(0 == (x & 0xFFFFFFFFULL)) {
		x >>= 32;
		register unsigned long i;
		i=ffs((_u32)x);
		return (int)i+31;
	} else {
		register unsigned long i;
		i=ffs((_u32)x);
		return (int)i-1;
	}
}

inline_ int first_msb_bit_indx64(_u64 x) {
	if(0==x)
		return -1;
	else if(0 == (x & 0xFFFFFFFFULL)) {
		x >>= 32;
		register unsigned long i;
		i=fls((_u32)x);
		return (int)i+31;
	} else {
		register unsigned long i;
		i=fls((_u32)x);
		return (int)i-1;
	}

}

#endif /* __SPARC64_DEFNS_H__ */
